package javase.collections;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

public class CopyOnWriteArrayListTest {
	private final static int INITIAL_LIST_CAPACITY = 10;
	private final static int NEW_ELEMENTS_AMOUNT = 10;

	private static volatile int newElementsMinValue = 100;

	public static void main(String[] args) {
		List<Integer> list = getInitializedCopyOnWriteArrayList();
		System.out.println("Created initial list " + list);

		Thread printer = new Thread(new ListPrinter(list), "printer");
		Thread modifier = new Thread(new ListModifier(list), "modifier");
//		Thread cleaner = new Thread(new ListCleaner(list), "modifier");

		System.out.println("Starting threads");
		printer.start();
		modifier.start();
//		cleaner.start();
		System.out.println("main " + list);
		System.out.println(" END  of main");
	}

	private static CopyOnWriteArrayList<Integer> getInitializedCopyOnWriteArrayList() {
		CopyOnWriteArrayList<Integer> result = new CopyOnWriteArrayList<Integer>();
		for (int i = 0; i < INITIAL_LIST_CAPACITY; i++) {
			result.add(i);
		}
		return result;
	}

	private static class ListModifier implements Runnable {
		private List<Integer> list;

		public ListModifier(List<Integer> list) {
			this.list = list;
		}

		@Override
		public void run() {
			System.out.println("ListModifier runs");
			while (true) {
				System.out.println("+++++++++++++++++START+++++++++++++++++++++++");
				for (int i = 0; i < NEW_ELEMENTS_AMOUNT; i++) {
					list.add(newElementsMinValue++);
					System.out.println("+ " + (newElementsMinValue - 1));
				}
				System.out.println("+++++++++++++++++ END +++++++++++++++++++++++");
			}
		}
	}

	private static class ListPrinter implements Runnable {
		private List<Integer> list;

		public ListPrinter(List<Integer> list) {
			this.list = list;
		}

		@Override
		public void run() {
			System.out.println("ListPrinter runs");
			while (true) {
				System.out.println("====================START===================");
				for (Integer current : list) {
					System.out.println("= " + current);
				}
				System.out.println("==================== END ===================");
			}
		}

	}

	@SuppressWarnings("unused")
	private static class ListCleaner implements Runnable {
		private List<Integer> list;

		public ListCleaner(List<Integer> list) {
			this.list = list;
		}

		@Override
		public void run() {
			System.out.println("ListCleaner runs");
			while (true) {
				System.out.println("-----------------START---------------------");
				for (int i = 0; i < 10; i++) {
					if (!list.isEmpty()) {
						System.out.println("- " + list.remove(0));
					}
				}
				System.out.println("----------------- END ---------------------");
			}
		}
	}
}
